package com.net.xpay.alipay.safePay;

import com.alipay.api.*;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.net.xpay.alipay.exception.AlipayClientException;
import com.net.xpay.alipay.model.*;
import com.net.xpay.alipay.model.AlipayFundAccountbookPageCreateModel;
import com.net.common.util.LocalDateUtil;
import com.net.common.util.SerializationUtil;
import com.net.xpay.alipay.model.*;
import com.net.xpay.alipay.request.AlipayFundAccountbookPageCreateRequest;
import com.net.xpay.common.domain.BookAccountTransferOrder;
import com.net.xpay.core.domain.safePay.BookAccountChargeOrder;
import com.net.xpay.core.domain.safePay.SafePayOrder;
import com.net.xpay.core.utils.GsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public class PoseidonSafePayAlipayClient {

    private boolean isDev = false;

    private AlipayClient alipayClient;

    private final int retryTimes;

    public PoseidonSafePayAlipayClient(AlipayClient alipayClient, int retryTimes) {
        this.alipayClient = alipayClient;
        this.retryTimes = retryTimes;
    }

    public PoseidonSafePayAlipayClient(AlipayClient alipayClient, int retryTimes, boolean isDev) {
        this.alipayClient = alipayClient;
        this.retryTimes = retryTimes;
        this.isDev = isDev;
    }

    private <T extends AlipayResponse> T autoRetryExecute(AlipayRequest<T> req) throws AlipayApiException {
        return execute(req);
    }

    public <T extends AlipayResponse> T execute(AlipayRequest<T> req)
            throws AlipayApiException {
        T alipayRsp = isDev ? alipayClient.execute(req) : alipayClient.certificateExecute(req);
        log.debug("execute alipayRsp={}", SerializationUtil.obj2String(alipayRsp));
        return alipayRsp;
    }

    private <T extends AlipayResponse> T pageExecute(AlipayRequest<T> req)
            throws AlipayClientException {
        T alipayRsp;
        try {
            alipayRsp = alipayClient.pageExecute(req, "get");
            log.debug("pageExecute alipayRsp={}", SerializationUtil.obj2String(alipayRsp));
        } catch (AlipayApiException e) {
            throw new AlipayClientException(e.getErrCode(), e.getErrMsg());
        }
        if (alipayRsp.isSuccess()) {
            return alipayRsp;
        }
        throw new AlipayClientException(alipayRsp.getCode(), alipayRsp.getMsg(), alipayRsp.getSubCode(), alipayRsp.getSubMsg());
    }

    //支付宝个人协议页面签约接口
    public String alipayUserAgreementPageSignCreate(String externalAgreementNo, String externalLogonId) {
        AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();

        TransModel transModel = new TransModel();
        transModel.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
        transModel.setSignScene("INDUSTRY|SATF_ACC");
        TransModel.AccessParams accessParams = new TransModel.AccessParams();
        accessParams.setChannel("QRCODE");
        transModel.setAccessParams(accessParams);
        transModel.setProductCode("FUND_SAFT_SIGN_WITHHOLDING");
        transModel.setExternalAgreementNo(externalAgreementNo);
        transModel.setThirdPartyType("PARTNER");
        transModel.setExternalLogonId(externalLogonId);
        request.setBizContent(GsonUtil.getGson().toJson(transModel));

        return pageExecute(request).getBody();
    }

    //支付宝注销接口
    public AlipayFundAccountbookCloseResponse closeAlipayFundAccountbook(String accountBookId, String agreementNo) throws AlipayApiException {
        AlipayFundAccountbookCloseRequest request = new AlipayFundAccountbookCloseRequest();
        AlipayFundAccountbookCloseModel closeModel  = new AlipayFundAccountbookCloseModel();
        closeModel.setSceneCode("SATF_FUND_BOOK");
        closeModel.setAccountBookId(accountBookId);
        AccountCloseBusinessParams businessParams = new AccountCloseBusinessParams();
        businessParams.setAgreementNo(agreementNo);
        closeModel.setBusinessParams(businessParams);

        request.setBizModel(closeModel);

        return autoRetryExecute(request);
    }


    //支付宝个人协议解除接口
    public AlipayUserAgreementUnsignResponse unSignAlipayUserAgreement(String externalAgreementNo) throws AlipayApiException {
        AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("external_agreement_no", externalAgreementNo);
        params.put("personal_product_code", "FUND_SAFT_SIGN_WITHHOLDING_P");
        params.put("sign_scene", "INDUSTRY|SATF_ACC");
        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }


    //支付宝个人协议页面签约结果查询
    public AlipayUserAgreementQueryResponse alipayUserAgreementQuery(String externalAgreementNo) throws AlipayApiException {
        AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("personal_product_code", "FUND_SAFT_SIGN_WITHHOLDING_P");
        params.put("sign_scene", "INDUSTRY|SATF_ACC");
        params.put("product_code", "FUND_SAFT_SIGN_WITHHOLDING");
        params.put("external_agreement_no", externalAgreementNo);//商户签约号

        request.setBizContent(GsonUtil.getGson().toJson(params));
        return autoRetryExecute(request);
    }

    //开通记账本
    public AlipayFundAccountbookCreateResponse alipayFundAccountbookCreate(String merchantUserId, String agreementNo) throws AlipayApiException {
        AlipayFundAccountbookCreateRequest request = new AlipayFundAccountbookCreateRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_user_id", merchantUserId);
        params.put("merchant_user_type", "BUSINESS_ORGANIZATION");
        params.put("scene_code", "SATF_FUND_BOOK");
        params.put("ext_info", "{\"agreement_no\":\"" + agreementNo + "\"}");
        request.setBizContent(GsonUtil.getGson().toJson(params));
        return autoRetryExecute(request);
    }

    //开通记账本 官方申请开通
    public String alipayFundAccountbookPageCreate(AlipayFundAccountbookPageCreateModel model) {
        AlipayFundAccountbookPageCreateRequest request = new AlipayFundAccountbookPageCreateRequest();
        model.setProductCode("FUND_ACCOUNT_BOOK");
        model.setBizScene("ACCOUNT_BOOK_PROXY_CREATE");
        request.setBizContent(GsonUtil.getGson().toJson(model));
        log.info("alipayFundAccountbookPageCreate bizContent={}", request.getBizContent());
        return pageExecute(request).getBody();
    }


    //订阅非openApi入金通知
    public AlipayFundAccountbookNotifySubscribeResponse alipayFundAccountbookNotifySubscribe(String accountBookId, String agreementNo) throws AlipayApiException {
        AlipayFundAccountbookNotifySubscribeRequest request = new AlipayFundAccountbookNotifySubscribeRequest();

        Map<String, Object> params = new HashMap<>();
        params.put("product_code", "SATF_FUND_BOOK");
        params.put("biz_scene", "DEFAULT");
        params.put("account_book_id", accountBookId);
        params.put("agreement_no", agreementNo);
        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }

    //资金专款拨入（商户自身给记账本充值)
    public String alipayFundTransPagePayFundAccountBook(BookAccountChargeOrder order) {
        AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
        FundTransPagePayModel pagePayModel = new FundTransPagePayModel();
        pagePayModel.setOutBizNo(order.getOutBizNo());
        pagePayModel.setTransAmount(order.getTransAmount().toString());
        pagePayModel.setProductCode("FUND_ACCOUNT_BOOK");
        pagePayModel.setBizScene("SATF_DEPOSIT");
        pagePayModel.setRemark(order.getRemark());
        pagePayModel.setOrderTitle(order.getOrderTitle());
        pagePayModel.setTimeExpire(LocalDateUtil.getDateTimeAsString(order.getTimeExpire()));

        FundTransPagePayModel.PayeeInfo payeeInfo = new FundTransPagePayModel.PayeeInfo();
        if (Strings.isNullOrEmpty(order.getAlipayUid())) {
            //新模式 不需要支付宝uid
            payeeInfo.setIdentity(order.getBookId());
            payeeInfo.setIdentityType("ACCOUNT_BOOK_ID");
            payeeInfo.setExtInfo("{\"agreement_no\":\"" + order.getAgreementNo() + "\"}");
        } else {
            payeeInfo.setIdentity(order.getAlipayUid());
            payeeInfo.setIdentityType("ALIPAY_USER_ID");
            payeeInfo.setExtInfo("{\"agreement_no\":\"" + order.getAgreementNo() + "\",\"account_book_id\":\"" + order.getBookId() + "\",\"accountbook_scene_code\":\"SATF_FUND_BOOK\"}");
        }

        pagePayModel.setPayeeInfo(payeeInfo);

        request.setBizContent(GsonUtil.getGson().toJson(pagePayModel));
        return pageExecute(request).getBody();
    }

    //记账本单笔转个人
    public AlipayFundTransUniTransferResponse uniTransferAlipayFundTrans(SafePayOrder order) throws AlipayApiException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        FundTransUniTransferModel transferModel = new FundTransUniTransferModel();
        transferModel.setOutBizNo(order.getOutBizNo());
        transferModel.setTransAmount(order.getTransAmount().toString());
        transferModel.setProductCode("SINGLE_TRANSFER_NO_PWD");
        transferModel.setBizScene("ENTRUST_TRANSFER");

        FundTransUniTransferModel.PayerInfo payerInfo = new FundTransUniTransferModel.PayerInfo();
        payerInfo.setIdentity(order.getBookId());
        payerInfo.setIdentityType("ACCOUNT_BOOK_ID");
        payerInfo.setExtInfo("{\"agreement_no\":\"" + order.getAgreementNo() + "\"}");
        transferModel.setPayerInfo(payerInfo);

        transferModel.setOrderTitle(order.getOrderTitle());
        transferModel.setRemark(order.getRemark());
        transferModel.setBusinessParams("{\"payer_show_name\":\"备付金账户\"}");

        FundTransUniTransferModel.PayeeInfo payeeInfo = new FundTransUniTransferModel.PayeeInfo();
        payeeInfo.setIdentity(order.getIdentity());
        payeeInfo.setIdentityType(order.getIdentityType());
        payeeInfo.setName(order.getName());
        transferModel.setPayeeInfo(payeeInfo);
        log.info("uniTransferAlipayFundTrans bizContent={}", GsonUtil.getGson().toJson(transferModel));
        request.setBizContent(GsonUtil.getGson().toJson(transferModel));

        return autoRetryExecute(request);
    }

    //记账本单笔转银行卡
    public AlipayFundTransUniTransferResponse uniTransferAlipayToBankFundTrans(
            SafePayOrder order
    ) throws AlipayApiException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        FundTransUniTransferModel transferModel = new FundTransUniTransferModel();
        transferModel.setOutBizNo(order.getOutBizNo());
        transferModel.setTransAmount(order.getTransAmount().toString());
        transferModel.setProductCode("SINGLE_TRANSFER_NO_PWD");
        transferModel.setBizScene("ENTRUST_TRANSFER");

        FundTransUniTransferModel.PayerInfo payerInfo = new FundTransUniTransferModel.PayerInfo();
        payerInfo.setIdentity(order.getBookId());
        payerInfo.setIdentityType("ACCOUNT_BOOK_ID");
        payerInfo.setExtInfo("{\"agreement_no\":\"" + order.getAgreementNo() + "\"}");
        transferModel.setPayerInfo(payerInfo);

        transferModel.setOrderTitle(order.getOrderTitle());
        transferModel.setRemark(order.getRemark());
        transferModel.setBusinessParams("{\"withdraw_timeliness\":\"T0\"}");

        FundTransUniTransferModel.PayeeInfo payeeInfo = new FundTransUniTransferModel.PayeeInfo();
        payeeInfo.setIdentity(order.getIdentity());//银行卡号
        payeeInfo.setIdentityType("BANKCARD_ACCOUNT");
        payeeInfo.setName(order.getName());
        FundTransUniTransferModel.BankcardExtInfo bankcardExtInfo = new FundTransUniTransferModel.BankcardExtInfo();
        bankcardExtInfo.setAccountType("2");
        payeeInfo.setBankcardExtInfo(bankcardExtInfo);
        transferModel.setPayeeInfo(payeeInfo);
        log.info("uniTransferAlipayToBankFundTrans bizContent={}", GsonUtil.getGson().toJson(transferModel));
        request.setBizContent(GsonUtil.getGson().toJson(transferModel));

        return autoRetryExecute(request);
    }

    //记账本调拨
    public AlipayFundTransUniTransferResponse uniTransferAlipayFundTransForBook(BookAccountTransferOrder order) throws AlipayApiException {
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        FundTransUniTransferModel transferModel = new FundTransUniTransferModel();
        transferModel.setOutBizNo(order.getOutBizNo());
        transferModel.setTransAmount(order.getTransAmount().toString());
        transferModel.setProductCode("SINGLE_TRANSFER_NO_PWD");
        transferModel.setBizScene("ENTRUST_ALLOCATION");

        FundTransUniTransferModel.PayerInfo payerInfo = new FundTransUniTransferModel.PayerInfo();
        payerInfo.setIdentity(order.getPayerBookId());
        payerInfo.setIdentityType("ACCOUNT_BOOK_ID");
        payerInfo.setExtInfo("{\"agreement_no\":\"" + order.getPayerAgreementNo() + "\"}");
        transferModel.setPayerInfo(payerInfo);

        transferModel.setOrderTitle(order.getOrderTitle());
        transferModel.setRemark(order.getRemark());

        FundTransUniTransferModel.PayeeInfo payeeInfo = new FundTransUniTransferModel.PayeeInfo();
        payeeInfo.setIdentity(order.getPayeeBookId());
        payeeInfo.setIdentityType("ACCOUNT_BOOK_ID");
        payeeInfo.setExtInfo("{\"agreement_no\":\"" + order.getPayeeAgreementNo() + "\"}");
        transferModel.setPayeeInfo(payeeInfo);
        log.info("uniTransferAlipayFundTransForBook bizContent={}", GsonUtil.getGson().toJson(transferModel));
        request.setBizContent(GsonUtil.getGson().toJson(transferModel));

        return autoRetryExecute(request);
    }

    //单笔转账结果查询
    public AlipayFundTransCommonQueryResponse queryTransferAlipayFundTrans(String outBizNo) throws AlipayApiException {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(outBizNo));
        AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("product_code", "SINGLE_TRANSFER_NO_PWD");
        params.put("biz_scene", "ENTRUST_TRANSFER");
        params.put("out_biz_no", outBizNo);

        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }

    //记账本充值结果查询
    public AlipayFundTransCommonQueryResponse queryAccountBookCharge(String outBizNo) throws AlipayApiException {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(outBizNo));
        AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("product_code", "FUND_ACCOUNT_BOOK");
        params.put("biz_scene", "COMANAGER_SATF_DEPOSIT");
        params.put("out_biz_no", outBizNo);

        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }

    //资金账本余额查询
    public AlipayFundAccountbookQueryResponse queryAlipayFundAccountbook(String bookId, String agreementNo) throws AlipayApiException {
        AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("account_book_id", bookId);
        params.put("scene_code", "SATF_FUND_BOOK");
        params.put("ext_info", "{\"agreement_no\":\"" + agreementNo + "\"}");

        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }

    //资金账本余额查询
    public AlipayFundAccountbookQueryResponse queryAlipayFundAccountbook(String outBizNo) throws AlipayApiException {
        AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
        Map<String, Object> params = new HashMap<>();
        params.put("merchant_user_id", outBizNo);
        params.put("scene_code", "SATF_FUND_BOOK");
        params.put("ext_info", "{\"relate_auth\":\"true\"}");
        request.setBizContent(GsonUtil.getGson().toJson(params));

        return autoRetryExecute(request);
    }

    //自用单笔资金转账
    public AlipayFundTransUniTransferResponse transferUniFund(@RequestBody TransferUniFundModel model) throws AlipayApiException {
        Preconditions.checkArgument(model != null);
        model.setBizScene("DIRECT_TRANSFER");
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        request.setBizContent(GsonUtil.getGson().toJson(model));
        return autoRetryExecute(request);
    }


    //创建单笔转账的回单申请
    public AlipayDataBillEreceiptagentApplyResponse applyAlipayDataBill(AlipayDataBillEreceiptagentApplyModel applyModel) throws AlipayApiException {
        AlipayDataBillEreceiptagentApplyRequest request = new AlipayDataBillEreceiptagentApplyRequest();
        applyModel.setType("FUND_DETAIL");
        request.setBizModel(applyModel);
        return autoRetryExecute(request);
    }

    //查询笔转账的回单申请下载链接
    public AlipayDataBillAccountbookereceiptQueryResponse queryAlipayDataBill(AlipayDataBillAccountbookereceiptQueryModel model) throws AlipayApiException {
        AlipayDataBillAccountbookereceiptQueryRequest request = new AlipayDataBillAccountbookereceiptQueryRequest();
        request.setBizModel(model);

        return autoRetryExecute(request);
    }

    /**
     * 零工卡业务
     */
    //零工卡开通
    public AlipayFundFlexiblestaffingEmployeehomeApplyResponse applyAlipayFundFlexiblestaffingEmployeehome(FundFlexiblestaffingEmployeehomeApplyModel applyModel, String returnUrl) throws AlipayApiException {
        AlipayFundFlexiblestaffingEmployeehomeApplyRequest request = new AlipayFundFlexiblestaffingEmployeehomeApplyRequest();

        applyModel.setProductCode("FLEXIBLE_EMPLOYMENT_SERVICE");
        applyModel.setBizScene("EMPLOYEE_HOME_MANAGE");

        applyModel.setApplyLinkType("SHORT_URL");
        applyModel.setChannel("tinyapp");
        applyModel.setBackUrl(returnUrl);

        request.setBizModel(applyModel);

        return autoRetryExecute(request);
    }

    //零工卡解约
    public AlipayFundFlexiblestaffingEmployeehomeUnsignResponse unsignAlipayFundFlexiblestaffingEmployeehome(AlipayFundFlexiblestaffingEmployeehomeUnsignModel model) throws AlipayApiException {
        model.setProductCode("FLEXIBLE_EMPLOYMENT_SERVICE");
        model.setBizScene("EMPLOYEE_HOME_MANAGE");
        model.setTerminateType("RENT_CONTRACT");

        AlipayFundFlexiblestaffingEmployeehomeUnsignRequest request = new AlipayFundFlexiblestaffingEmployeehomeUnsignRequest();
        request.setBizModel(model);

        return autoRetryExecute(request);
    }

    //开卡结果查询
    public AlipayFundFlexiblestaffingEmployeehomeQueryResponse queryAlipayFundFlexiblestaffingEmployeehome(AlipayFundFlexiblestaffingEmployeehomeQueryModel model) throws AlipayApiException {
        AlipayFundFlexiblestaffingEmployeehomeQueryRequest request = new AlipayFundFlexiblestaffingEmployeehomeQueryRequest();
        request.setBizModel(model);

        return autoRetryExecute(request);
    }

    //零工卡还款
    public AlipayFundFlexiblestaffingRepaymentTransferResponse transferAlipayFundFlexiblestaffingRepayment(AlipayFundFlexiblestaffingRepaymentTransferModel model) throws AlipayApiException {
        AlipayFundFlexiblestaffingRepaymentTransferRequest request = new AlipayFundFlexiblestaffingRepaymentTransferRequest();
        request.setBizModel(model);

        return autoRetryExecute(request);
    }

    //零工卡人脸验证
    public AlipayFundFlexiblestaffingAuthenticationApplyResponse applyAlipayFundFlexiblestaffingAuthentication(AlipayFundFlexiblestaffingAuthenticationApplyModel model) throws AlipayApiException {
        AlipayFundFlexiblestaffingAuthenticationApplyRequest request = new AlipayFundFlexiblestaffingAuthenticationApplyRequest();
        model.setProductCode("FLEXIBLE_EMPLOYMENT_SERVICE");
        model.setBizScene("FACE_AUTHENTICATION"); //

        request.setBizModel(model);

        return autoRetryExecute(request);
    }


    public AlipayFundFlexiblestaffingAuthenticationQueryResponse queryAlipayFundFlexiblestaffingAuthentication(AlipayFundFlexiblestaffingAuthenticationQueryModel model) throws AlipayApiException {
        AlipayFundFlexiblestaffingAuthenticationQueryRequest request = new AlipayFundFlexiblestaffingAuthenticationQueryRequest();
        model.setProductCode("FLEXIBLE_EMPLOYMENT_SERVICE");
        model.setBizScene("FACE_AUTHENTICATION");
        request.setBizModel(model);

        return autoRetryExecute(request);
    }


}
